package com.test.multithread.atomic3;

import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;

class SaleThread implements Runnable {

    /**
     * 使用静态成员变量作为100张票的保存变量，是一个共享资源。
     */
    //todo 这里是最重要的，现在需要找出，可以用什么来替代锁。解决可见性，有效性，原子性
    private static AtomicInteger tickets = new AtomicInteger(99);
    private static Semaphore semaphore = new Semaphore(1);

    @Override
    public void run() {
        count();
    }

    private void count() {
        // 完成售票过程
        while (tickets.get() >= 1) {
            try {
                Thread.sleep(50);
                //1.todo 要跳出循环，必须在循环的那级，进行return
                //2. todo 输出条件，也要放在锁内，就是为了解决现场安全的问题。（也就是，整个流程的开始到结束，都要放进去）
                //3. todo 否则当条件为tickets.get() == 0 时，线程是不会停止的，要搞清楚为什么会有第0张票。读到的，不代表不会改变 */
                    sell();

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /*A. 无论synchronized关键字加在方法上还是对象上，如果它作用的对象是非静态的，则它取得的锁是对象；
    如果synchronized作用的对象是一个静态方法或一个类，则它取得的锁是对类，该类所有的对象同一把锁。
    B. 每个对象只有一个锁（lock）与之相关联，谁拿到这个锁谁就可以运行它所控制的那段代码。
    C. 实现同步是要很大的系统开销作为代价的，甚至可能造成死锁，所以尽量避免无谓的同步控制。*/
    private static synchronized void sell() {
        if (tickets.get() == 0) {
            System.out.println(Thread.currentThread().getName() + "进入到票售罄的地方,不应该有第0张票");
            return;
        } else {
            //semaphore.acquire();
            System.out.println(Thread.currentThread().getName() + "售出了第" + tickets.getAndDecrement() + "张票");
            ///semaphore.release();
            //需要解决为什么在这和在上面是不一样的
            //tickets.getAndDecrement();
        }

    }
}

public class Demo {
    public static void main(String[] args) {
        Thread t1 = new Thread(new SaleThread(), "售票人员1");
        Thread t2 = new Thread(new SaleThread(), "售票人员2");
        Thread t3 = new Thread(new SaleThread(), "售票人员3");

        t1.start();
        t2.start();
        t3.start();
    }
}